# Copyright 2023 Specter Ops, Inc.
#
# Licensed under the Apache License, Version 2.0
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# SPDX-License-Identifier: Apache-2.0

version: '3'

services:
  proxy:
    image: docker.io/library/traefik:latest
    command:
      - --api.insecure=true
      - --providers.docker
      - --providers.docker.exposedbydefault=false
    ports:
      - ${WEB_PORT:-127.0.0.1:80}:80
      - ${TRAEFIK_PORT:-127.0.0.1:8000}:8080
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro

  app-db:
    image: docker.io/library/postgres:13.2
    environment:
      - POSTGRES_USER=${BH_POSTGRES_USER:-bloodhound}
      - POSTGRES_PASSWORD=${BH_POSTGRES_PASSWORD:-bloodhoundcommunityedition}
      - POSTGRES_DB=${BH_POSTGRES_DB:-bloodhound}
    ports:
      - ${BH_POSTGRES_PORT:-127.0.0.1:5432}:5432
    volumes:
      - ${BH_POSTGRES_VOLUME:-postgres-data}:/var/lib/postgresql/data
    healthcheck:
      test:
        [
          "CMD-SHELL",
          "pg_isready -U ${BH_POSTGRES_USER:-bloodhound} -d 'dbname=${BH_POSTGRES_DB:-bloodhound}' -h 127.0.0.1 -p 5432"
        ]
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 30s

  pgadmin:
    build:
      context: tools/docker-compose
      dockerfile: pgadmin.Dockerfile
    environment:
      PGADMIN_DEFAULT_EMAIL: ${BH_PG_ADMIN_EMAIL:-bloodhound@specterops.io}
      PGADMIN_DEFAULT_PASSWORD: ${BH_PG_ADMIN_PASSWORD:-bloodhoundcommunityedition}
      PGADMIN_LISTEN_PORT: 5050
    ports:
      - ${BH_PG_ADMIN_PORT:-127.0.0.1:5050}:5050
    labels:
      - traefik.enable=true
      - traefik.http.routers.pgadmin.rule=Host(`${BH_PG_ADMIN_HOSTNAME:-pgadmin.localhost}`)
      - traefik.http.routers.pgadmin.service=pgadmin
      - traefik.http.services.pgadmin.loadbalancer.server.port=5050
    depends_on:
      app-db:
        condition: service_healthy

  graph-db:
    build:
      context: tools/docker-compose
      dockerfile: neo4j.Dockerfile
    environment:
      - NEO4J_AUTH=${BH_NEO4J_AUTH:-neo4j/bloodhoundcommunityedition}
      - NEO4J_dbms_allow__upgrade=${BH_NEO4J_ALLOW_UPGRADE:-true}
    ports:
      - ${BH_NEO4J_PORT:-127.0.0.1:7687}:7687
      - ${BH_NEO4J_WEB_PORT:-127.0.0.1:7474}:7474
    volumes:
      - ${BH_NEO4J_VOLUME:-neo4j-data}:/data
    labels:
      - traefik.enable=true
      - traefik.http.routers.neo4jbrowser.rule=Host(`${BH_NEO4J_HOSTNAME:-neo4j.localhost}`)
      - traefik.http.routers.neo4jbrowser.service=neo4jbrowser
      - traefik.http.services.neo4jbrowser.loadbalancer.server.port=7474
    healthcheck:
      test:
        [
          "CMD-SHELL",
          "wget -O /dev/null -q http://localhost:7474 || exit 1"
        ]
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 30s

  bh-api:
    profiles:
      - dev
      - api-only
    build:
      context: tools/docker-compose
      dockerfile: api.Dockerfile
    command: "-c .air.toml ${AIR_FLAGS:-''}"
    ports:
      - ${BH_API_PORT:-127.0.0.1:8080}:8080
    labels:
      - traefik.enable=true
      - traefik.http.routers.bhapi.rule=Host(`${BH_HOSTNAME:-bloodhound.localhost}`) && PathPrefix(`/api`)
      - traefik.http.routers.bhapi.service=bhapi
      - traefik.http.services.bhapi.loadbalancer.server.port=8080
    volumes:
      - .:/bloodhound:ro
      - ./local-harnesses/${BH_CONFIG_FILE:-build.config.json}:/build.config.json:ro
      - go-pkg-mod:/go/pkg/mod
    depends_on:
      app-db:
        condition: service_healthy
      graph-db:
        condition: service_healthy

  bh-ui:
    profiles:
      - dev
      - ui-only
      - debug-api
    build:
      context: .
      dockerfile: tools/docker-compose/ui.Dockerfile
    command: sh -c "yarn dev"
    labels:
      - traefik.enable=true
      - traefik.http.routers.bhui.rule=Host(`${BH_HOSTNAME:-bloodhound.localhost}`)
      - traefik.http.middlewares.add-bh-ui.addprefix.prefix=/ui
      - traefik.http.routers.bhui.service=bhui
      - traefik.http.services.bhui.loadbalancer.server.port=3000
    volumes:
      - ./cmd/ui/public:/bloodhound/cmd/ui/public:ro
      - ./cmd/ui/src:/bloodhound/cmd/ui/src:ro
      - ./packages/javascript/bh-shared-ui/src:/bloodhound/packages/javascript/bh-shared-ui/src:ro
      - ./packages/javascript/js-client-library/src:/bloodhound/packages/javascript/js-client-library/src:ro
      - ui-cache:/.cache

  debug-api:
    profiles:
      - debug-api
    build:
      context: tools/docker-compose
      dockerfile: api.Dockerfile
    command: "-c .air.debug.toml ${AIR_FLAGS:-''}"
    ports:
      - ${BH_API_PORT:-127.0.0.1:8080}:8080
      - ${DEBUG_PORT:-127.0.0.1:3456}:2345
    labels:
      - traefik.enable=true
      - traefik.http.routers.debugapi.rule=Host(`${BH_HOSTNAME:-bloodhound.localhost}`) && PathPrefix(`/api`)
      - traefik.http.routers.debugapi.service=debugapi
      - traefik.http.services.debugapi.loadbalancer.server.port=8080
    volumes:
      - .:/bloodhound:ro
      - ./local-harnesses/${BH_CONFIG_FILE:-build.config.json}:/build.config.json:ro
    depends_on:
      app-db:
        condition: service_healthy
      graph-db:
        condition: service_healthy

volumes:
  neo4j-data:
  postgres-data:
  go-pkg-mod:
  ui-cache:
